
import { Vector3 } from "../base_frame/math/Vector3";
import { LightCube } from "./LightCube";

export class PointLightSphere02 extends LightCube {



    protected readonly VS: string =
        "attribute vec4 a_Position;\n" +
        "attribute vec4 a_Color;\n" +
        "attribute vec4 a_Normal;\n" +
        "varying vec3 v_Position;\n" +
        "varying vec3 v_Normal;\n" +
        "varying vec4 v_Color;\n" +
        "uniform mat4 u_MvpMatrix;\n" +
        "uniform mat4 u_NormalMatrix;\n" +

        "void main(){\n" +
        "   v_Normal = vec3(u_NormalMatrix * a_Normal);\n" +
        "   vec4 realPos = u_MvpMatrix * a_Position;\n" +
        "   v_Position = realPos.xyz;\n" +
        "   v_Color = a_Color;\n" +
        "   gl_Position = realPos;\n" +
        "}\n";

    protected readonly FS: string =
        "precision mediump float;\n" +
        "varying vec4 v_Color;\n" +
        "varying vec3 v_Position;\n" +
        "varying vec3 v_Normal;\n" +
        "uniform vec3 u_LightPosition;\n" +
        "uniform vec3 u_LightColor;\n" +
        "uniform vec3 u_AmbientColor;\n" +
        "void main(){\n" +
        // "   vec3 lightDir = normalize(v_Position - u_LightPosition);\n" +
        "   vec3 lightDir = normalize(u_LightPosition - v_Position);\n" +
        "   vec3 normal = normalize(v_Normal);\n" +
        "   vec3 diffuseColor = max(dot(lightDir,normal),0.0)*u_LightColor*v_Color.rgb;\n" +
        "   vec3 realColor = diffuseColor + u_AmbientColor*v_Color.rgb;\n" +
        "   gl_FragColor = vec4(realColor, v_Color.a);\n" +
        "}\n";

    private _lightPosition: Vector3 = new Vector3(3.0, 2.2, 0.0);

    private u_LightPosition: WebGLUniformLocation;

    initRef(gl: WebGL2RenderingContext | WebGLRenderingContext): void {
        //@ts-ignore
        let program = gl.program;
        this.a_Position = gl.getAttribLocation(program, "a_Position");
        this.a_Color = gl.getAttribLocation(program, "a_Color");
        this.a_Normal = gl.getAttribLocation(program, "a_Normal");
        this.u_LightColor = gl.getUniformLocation(program, "u_LightColor");
        this.u_AmbientColor = gl.getUniformLocation(program, "u_AmbientColor");
        this.u_LightPosition = gl.getUniformLocation(program, "u_LightPosition");
        this.u_NormalMatrix = gl.getUniformLocation(program, "u_NormalMatrix");
    }

    initValue(gl: WebGL2RenderingContext | WebGLRenderingContext) {
        let vec3 = this._lightPosition;
        gl.uniform3f(this.u_LightPosition, vec3.x, vec3.y, vec3.z);
        gl.uniform3f(this.u_LightColor, 1.0, 1.0, 1.0);
        gl.uniformMatrix4fv(this.u_NormalMatrix, false, this.normalMatrix.elements);
        gl.uniform3f(this.u_AmbientColor, 0.2, 0.2, 0.2);
        gl.vertexAttrib4f(this.a_Color, 1.0, 1.0, 1.0, 1.0); // 之前没设置颜色缓冲，导致没有设置颜色的值，现在给个默认的值

    }


    initBuffer(gl: WebGL2RenderingContext | WebGLRenderingContext) { // Create a sphere
        var SPHERE_DIV = 13;

        var i, ai, si, ci;
        var j, aj, sj, cj;
        var p1, p2;

        var positions = [];
        var indices = [];

        // Generate coordinates
        for (j = 0; j <= SPHERE_DIV; j++) {
            aj = j * Math.PI / SPHERE_DIV;
            sj = Math.sin(aj);
            cj = Math.cos(aj);
            for (i = 0; i <= SPHERE_DIV; i++) {
                ai = i * 2 * Math.PI / SPHERE_DIV;
                si = Math.sin(ai);
                ci = Math.cos(ai);

                positions.push(si * sj);  // X
                positions.push(cj);       // Y
                positions.push(ci * sj);  // Z
            }
        }

        // Generate indices
        for (j = 0; j < SPHERE_DIV; j++) {
            for (i = 0; i < SPHERE_DIV; i++) {
                p1 = j * (SPHERE_DIV + 1) + i;
                p2 = p1 + (SPHERE_DIV + 1);

                indices.push(p1);
                indices.push(p2);
                indices.push(p1 + 1);

                indices.push(p1 + 1);
                indices.push(p2);
                indices.push(p2 + 1);
            }
        }

        // Write the vertex property to buffers (coordinates and normals)
        // Same data can be used for vertex and normal
        // In order to make it intelligible, another buffer is prepared separately
        let datas = new Float32Array(positions);
        if (!this.initArrayBuffer(gl, 'a_Position', datas, gl.FLOAT, 3)) return -1;
        if (!this.initArrayBuffer(gl, 'a_Normal', datas, gl.FLOAT, 3)) return -1;

        // this._createBuffer(this.a_Position, 3, gl.FLOAT, new Float32Array(positions), gl);
        // this._createBuffer(this.a_Normal, 3, gl.FLOAT, new Float32Array(positions), gl);
        // Unbind the buffer object
        gl.bindBuffer(gl.ARRAY_BUFFER, null);

        // Write the indices to the buffer object
        var indexBuffer = gl.createBuffer();
        if (!indexBuffer) {
            console.log('Failed to create the buffer object');
            return -1;
        }
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

        return indices.length;
    }

    initArrayBuffer(gl: WebGL2RenderingContext | WebGLRenderingContext, attribute: string, data: any, type: number, num: number) {
        // Create a buffer object
        var buffer = gl.createBuffer();
        if (!buffer) {
            console.log('Failed to create the buffer object');
            return false;
        }
        // Write date into the buffer object
        gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
        gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
        //@ts-ignore  // Assign the buffer object to the attribute variable
        var a_attribute = gl.getAttribLocation(gl.program, attribute);
        if (a_attribute < 0) {
            console.log('Failed to get the storage location of ' + attribute);
            return false;
        }
        gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);
        // Enable the assignment of the buffer object to the attribute variable
        gl.enableVertexAttribArray(a_attribute);

        gl.bindBuffer(gl.ARRAY_BUFFER, null);

        return true;
    }

    draw(gl: WebGL2RenderingContext | WebGLRenderingContext): void {

        gl.drawElements(gl.TRIANGLES, this._count, gl.UNSIGNED_SHORT, 0);
    }

}